package com.jianggy.jsonpath;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONPath;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * json parse
 *
 * @author jianggy
 * @version 1.0
 * @time 2019/4/19 18:30
 * @see
 **/
public class JSONParse {
    public static final String SEPARATOR = "@@@&&&&&@@@";

    public static List<String> parse(String sourceJson, String[] paths) {
        List<JSONField> jsonFields = JSONParse.jsonToJSONField(paths, sourceJson);
        List<String> resList = JSONParse.parseList(jsonFields);
        return resList;
    }

    private static int lengthOrder(List<JSONField> fields) {
        int length = 1;
        for (Iterator<JSONField> iterator = fields.iterator(); iterator.hasNext(); ) {
            JSONField field = iterator.next();
            if (field.getLength() > length) {
                length = field.getLength();
            }
        }
        System.out.println("the max length is：" + length);
        return length;
    }

    /**
     * This method parse the list to multi row, per JSONField represent a column, the JSONField's max size represent row number
     * in other words, the list size is the result's column amount,the max value of the JSONField's length property is returned list size
     */

    public static List<String> parseList(List<JSONField> jsonFields) {
        List<String> resList = new ArrayList<>();
        int maxLength = lengthOrder(jsonFields);
        for (int i = 0; i < maxLength; i++) {
            StringBuilder sb = new StringBuilder();
            for (JSONField jsonField : jsonFields) {
                if (jsonField == null) {
                    sb.append("");
                    sb.append(SEPARATOR);
                    continue;
                }
                JSONArray array = (JSONArray) jsonField.getValue();
                if (array.size() > i) {
                    sb.append(array.getString(i));
                } else {
                    sb.append("");
                }
                sb.append(SEPARATOR);
            }
            int lastIndex = sb.lastIndexOf(SEPARATOR);
            sb.delete(lastIndex, lastIndex + SEPARATOR.length());
            resList.add(sb.toString());
        }
        return resList;
    }

    /**
     * convert the values of each path to a JSONField
     *
     * @param paths      json field path,format is xx.xx
     * @param sourceJson the string which will be parsed
     * @return
     * @throws
     */
    public static List<JSONField> jsonToJSONField(String[] paths, String sourceJson) {
        List<JSONField> jsonFields = new ArrayList<>();
        for (int i = 0; i < paths.length; i++) {
            Object obj = JSONPath.read(sourceJson, paths[i]);
            JSONField field = new JSONField();
            if (obj == null) {
                field.setLength(0);
                field.setType(0);
                continue;
            }
            if (obj instanceof com.alibaba.fastjson.JSONArray) {
                JSONArray array = (JSONArray) obj;
                field.setLength(array.size());
                field.setType(3);
            } else if (obj instanceof com.alibaba.fastjson.JSONObject) {
                obj = JSONArray.parseArray("[" + obj.toString() + "]");
                field.setType(2);
                field.setLength(1);
            } else {
                obj = JSONArray.parseArray("[\"" + obj.toString() + "\"]");
                field.setLength(1);
                field.setType(1);
            }
            field.setValue(obj);
            jsonFields.add(field);
        }
        return jsonFields;
    }
}
